import { $ } from '.'
import { runtimeConfig } from '../config/runtimeConfig'
import { modules } from '../module/index'

// 快照示例
const snapshotExample = {
    __type__: 'log',
    bus1: 0,
    bus2: 0,
    bus3: 0,
    bus4: 0,
    au: {
        au_en: 0,
        ac: 0,
        au_gf: 0,
    },
    pc: {
        in_pc: 1,
        ld_pc: 0,
        addr: 0,
    },
    ram: {
        re: 0,
        wr: 1,
        selAddr: 0,
    },
    multiplexer21: {
        s0: 1,
        value: 0,
    },
    multiplexer31: {
        s2: 0,
        s1: 0,
        value: 0,
    },
    reg: {
        sr1: 0,
        sr0: 0,
        dr1: 0,
        dr0: 0,
        we: 0,
        r0: 1,
        r1: 0,
        r2: 0,
        r3: 7,
    },
    psw: {
        g_en: 0,
        gf: 0,
    },
    ir: {
        ld_ir: 1,
        value: 0,
    },
    sm: {
        sm_en: 1,
        sm_value: 0,
    },
    decoder: {
        ins: '(EMPTY)',
    },
    output: {
        out_en: 0,
        value: 0,
    },
    input: {
        in_en: 0,
        value: 0,
    },
}

type SnapshotType = typeof snapshotExample

// 快照数组
const snapshots: any[] = []

// 获取渲染的容器，用选择器选中，如果有直接返回，没有时创建
function getSnapshotItemContainer(key: string) {
    let dom = $(`.snapshot-item-container-${key}`)
    if (dom) {
        return dom
    }
    dom = document.createElement('div')
    dom.classList.add(`row`)
    dom.classList.add(`snapshot-item-container-${key}`)
    // 内层div
    const div = document.createElement('div')
    div.textContent = key
    dom.appendChild(div)
    $('.snapshots-container')?.appendChild(dom)
    return dom
}

// 将快照渲染到页面中
function renderSnapshotsToDom(snapshot: any) {
    for (const key in snapshot) {
        const element = snapshot[key]
        if (key == '__type__' || key.startsWith('bus')) {
            const div = document.createElement('div')
            div.textContent = element
            div.classList.add(element)
            getSnapshotItemContainer(key)?.appendChild(div)
            continue
        }
        // 每一个对象
        for (let key2 in element) {
            const item = element[key2]
            if (key2 == 'value') {
                key2 = key
            }
            // 最外层的div
            const container = getSnapshotItemContainer(key2)
            const div = document.createElement('div')
            div.textContent = item
            container.appendChild(div)
        }
    }
    $('.snapshots-container')!.scrollLeft = 999999
}

const sText = {
    rise: '上升沿',
    neg: '下降沿',
}

export const logger = {
    // 对所有模块的状态拍摄快照
    snapshot(type: 'rise' | 'neg' | 'log' = 'log', toDom = true) {
        if (type != 'log' && runtimeConfig.snapshot[type] == false) {
            return
        }
        const snapshot: Partial<SnapshotType> = {}
        for (const module of modules) {
            if (module.name.startsWith('bus')) {
                // @ts-ignore
                snapshot[module.name] = module.getData()
            }
            // @ts-ignore
            if (module.state) {
                // @ts-ignore
                snapshot[module.name] = { ...module.state }
            }
        }
        // 是否渲染到dom中
        if (toDom) {
            renderSnapshotsToDom(snapshot)
            snapshots.push(snapshot)
        }
        return snapshot as Required<SnapshotType>
    },
    // 根据当前状态生成文本
    snapshotToText(type?: 'rise' | 'neg', toDom = true) {
        if (!type) {
            return
        }
        // 获取所有模块的当前状态
        const snapshot = this.snapshot()
        // 开始拼接文本
        let text = '提示：\n'
        // 时钟上升沿/下降沿到达，此时
        text += `${sText[type]}到达，此时\n`
        // 程序计数器pc
        text += `程序计数器pc: `
        if (type === 'rise') {
            text += '不工作。\n'
        } else {
            const { in_pc, ld_pc, addr } = snapshot!.pc
            if (in_pc === 1) {
                text += `in_pc为1，因此addr自增1，addr从${addr}变为${
                    addr + 1
                }\n`
            } else if (ld_pc === 1) {
                text += `ld_pc为1，因此程序计数器从输入端中加载数据。\n`
            }
        }
        if (!toDom) {
            return undefined
        }
        return text
    },
    getSnapshots() {
        return snapshots
    },
    resetSnapshots() {
        snapshots.splice(0, snapshots.length)
    },
}
